package com.diaohw.platform.framework.redis.util;

import cn.hutool.extra.spring.SpringUtil;
import org.springframework.data.redis.core.ZSetOperations;

import java.util.List;
import java.util.Set;

/**
 * @author 刁海文
 * @since 2023/9/19 20:34
 */
public class RedisZSetUtil {
    private final static ZSetOperations zSet = SpringUtil.getBean(ZSetOperations.class);

    /**
     * 添加值
     *
     * @param key   键
     * @param value 值
     * @param score 分数
     */
    public static <T> Boolean setCacheValue(String key, T value, double score) {
        return zSet.add(key, value, score);
    }

    /**
     * 添加值
     *
     * @param key   键
     * @param value 值
     * @param score 分数
     * @param time  过期时间
     */
    public static <T> Boolean setCacheValue(String key, T value, Double score, long time) {
        Boolean add = zSet.add(key, value, score);
        RedisUtil.expire(key, time);
        return add;
    }

    /**
     * 添加值
     *
     * @param key    键
     * @param values 值
     */
    public static <T> Long setCache(String key, Set<ZSetOperations.TypedTuple<T>> values) {
        return zSet.add(key, values);
    }

    /**
     * 添加值
     *
     * @param key    键
     * @param values 值
     * @param time   过期时间
     */
    public static <T> Long setCache(String key, Set<ZSetOperations.TypedTuple<T>> values, long time) {
        Long count = zSet.add(key, values);
        RedisUtil.expire(key, time);
        return count;
    }

    /**
     * 返回所有的分数
     *
     * @param key 键
     */
    public static <T> Set<T> allZSet(String key) {
        return rangeByScore(key, Double.MIN_VALUE, Double.MAX_VALUE);
    }

    /**
     * 返回所有的元素
     *
     * @param key 键
     */
    public static <T> Set<ZSetOperations.TypedTuple<T>> allZSetWithScores(String key) {
        return rangeByScoreWithScores(key, Double.MIN_VALUE, Double.MAX_VALUE);
    }


    /**
     * 获取指定分数区间的元素，不返回分数
     *
     * @param key      键
     * @param minScore 最小分数
     * @param maxScore 最大分数
     */
    public static <T> Set<T> rangeByScore(String key, double minScore, double maxScore) {
        return zSet.rangeByScore(key, minScore, maxScore);
    }

    /**
     * 获取指定分数区间的元素并返回分数
     *
     * @param key      键
     * @param minScore 最小分数
     * @param maxScore 最大分数
     */
    public static <T> Set<ZSetOperations.TypedTuple<T>> rangeByScoreWithScores(String key, double minScore, double maxScore) {
        return zSet.rangeByScoreWithScores(key, minScore, maxScore);
    }

    /**
     * 移除分数区间的元素
     *
     * @param key      键
     * @param minScore 最小分数
     * @param maxScore 最大分数
     */
    public static <T> Long removeRangeByScore(String key, double minScore, double maxScore) {
        return zSet.removeRangeByScore(key, minScore, maxScore);
    }

    /**
     * 移除指定元素
     *
     * @param key    键
     * @param values 元素值
     */
    public static <T> Long removeByValue(String key, T... values) {
        return zSet.remove(key, values);
    }

    /**
     * 移除指定元素
     *
     * @param key    键
     * @param values 元素值
     */
    public static <T> Long removeByValue(String key, List<T> values) {
        Object[] objects = values.toArray();
        return zSet.remove(key, objects);
    }

    /**
     * 返回分数最小的一个元素
     *
     * @param key 键
     */
    public static <T> ZSetOperations.TypedTuple<T> popMin(String key) {
        return (ZSetOperations.TypedTuple<T>) zSet.popMin(key);
    }

    /**
     * 返回分数最小的多个元素
     *
     * @param key 键
     */

    public static <T> Set<ZSetOperations.TypedTuple<T>> popMin(String key, long count) {
        return (Set<ZSetOperations.TypedTuple<T>>) zSet.popMin(key, count);
    }

    /**
     * 返回分数最大的一个元素
     *
     * @param key 键
     */
    public static <T> ZSetOperations.TypedTuple<T> popMax(String key) {
        return (ZSetOperations.TypedTuple<T>) zSet.popMax(key);
    }

    /**
     * 返回分数最大的多个元素
     *
     * @param key 键
     */
    public static <T> Set<ZSetOperations.TypedTuple<T>> popMax(String key, long count) {
        return (Set<ZSetOperations.TypedTuple<T>>) zSet.popMax(key, count);
    }
}
